<template>
  <a-select
    v-model="defaultValue"
    :placeholder="placeholder"
    :size="size"
    allow-clear
    :mode="!radio ? 'multiple' : 'default'"
    show-search
    :style="{
      width: width,
    }"
    :filter-option="false"
    label-in-value
    @search="fetch"
    @change="handleChange"
  >
    <a-spin v-if="fetching" slot="notFoundContent" size="small" />
    <a-select-option
      v-for="(element, index) in selectArray"
      :key="index"
      :value="element.value"
    >
      {{ element.label }}
    </a-select-option>
  </a-select>
</template>

<script>
export default {
  model: {
    event: "change-model",
    prop: "modelValue",
  },
  props: {
    width: {
      type: String,
      default: "230px",
    },
    radio: {
      type: Boolean,
      default: false,
    },
    selected: {
      type: Boolean,
      default: false,
    },
    extData: {
      // 父元素传递的数据， 原封不动 回调
      type: [Number, String, Array, Object],
      default: undefined,
    },
    placeholder: {
      type: String,
      default: "请选择",
    },
    size: {
      type: String,
      default: "default",
    },
    url: {
      type: String,
      default: undefined,
    },
    modelValue: {
      type: [Array, Number, String],
      default: () => {
        return undefined
      },
    },
    idIn: {
      type: String,
      default: "id_in",
    },
    searchMap: {
      type: Object,
      default: () => {
        return {}
      },
    },
    init: {
      type: Function,
      default: () => {
        return undefined
      },
    },
  },
  data() {
    this.fetch = this.$debounce(this.fetch, 600)
    return {
      haveSearchObj: {},
      selectArray: [],
      defaultSelectArray: undefined,
      fetching: false,
      defaultValue: undefined,

      firstFlag: true,
      emitChange: false,
      oldSearchKey: undefined,
      oldSearchMap: undefined,
    }
  },
  computed: {
    modelValueKey: function () {
      return JSON.stringify(this.modelValue)
    },
    searchMapKey: function () {
      return JSON.stringify(this.searchMap)
    },
  },
  watch: {
    modelValueKey() {
      if (
        !this.modelValue &&
        this.defaultSelectArray &&
        this.defaultSelectArray.length > 0
      ) {
        this.selectArray = this.defaultSelectArray
      }

      if (this.emitChange) {
        this.emitChange = false
        return
      }

      this.pageInit()
    },
    searchMapKey() {
      this.fetch()
    },
  },
  mounted() {
    this.pageInit()
  },
  methods: {
    async pageInit() {
      if (!this.url) return

      if (this.firstFlag) {
        this.firstFlag = false
        await this.fetch()
      }

      //页面初始化
      let defaultValue = []
      if (this.$func.isNumber(this.modelValue) && this.modelValue * 1 > 0) {
        defaultValue.push(this.modelValue * 1)
      } else if (this.$func.isString(this.modelValue)) {
        defaultValue.push(this.modelValue)
      } else {
        if (this.$func.isArray(this.modelValue) && this.modelValue.length > 0) {
          for (let ii in this.modelValue) {
            if (
              this.$func.isNumber(this.modelValue[ii]) &&
              this.modelValue[ii] * 1 > 0
            ) {
              defaultValue.push(this.modelValue[ii] * 1)
            }
          }
        }
      }

      if (defaultValue.length <= 0) {
        this.defaultValue = undefined
        return
      }

      let id_in = []
      for (let ii in defaultValue) {
        if (
          !Object.prototype.hasOwnProperty.call(
            this.haveSearchObj,
            defaultValue[ii]
          )
        ) {
          id_in.push(defaultValue[ii])
        }
      }
      if (id_in.length > 0) {
        let initObj = {}
        initObj[this.idIn] = id_in.join(",")
        await this.$http.get(this.url, initObj).then((res) => {
          if (res.code != 1) return
          let tmpArray = this.init(res.data)
          for (let ii in tmpArray) {
            this.haveSearchObj[tmpArray[ii]["value"]] = {
              ...tmpArray[ii],
              key: tmpArray[ii]["value"],
            }
          }
        })
      }
      if (this.radio) {
        this.defaultValue = undefined
        for (let ii in defaultValue) {
          if (
            Object.prototype.hasOwnProperty.call(
              this.haveSearchObj,
              defaultValue[ii]
            )
          ) {
            this.defaultValue = this.haveSearchObj[defaultValue[ii]]
          }
          break
        }
      } else {
        this.defaultValue = []
        for (let ii in defaultValue) {
          if (
            Object.prototype.hasOwnProperty.call(
              this.haveSearchObj,
              defaultValue[ii]
            )
          ) {
            this.defaultValue.push(this.haveSearchObj[defaultValue[ii]])
          }
        }
      }
    },
    async fetch(value) {
      if (!this.url) return

      this.oldSearchKey = value
      this.oldSearchMap = this.searchMap

      this.selectArray = []
      this.fetching = true

      let defaultValue = undefined
      await this.$http
        .get(this.url, {
          ...this.searchMap,
          searchkey: value,
          page: 1,
          pageSize: 30,
        })
        .then((response) => {
          if (response.code !== 1) {
            this.$message.warning(response.message)
            return
          }
          if (this.init) this.selectArray = this.init(response.data)

          for (let ii in this.selectArray) {
            let tmpObj = {
              ...this.selectArray[ii],
              key: this.selectArray[ii]["value"],
            }

            this.haveSearchObj[this.selectArray[ii]["value"]] = tmpObj
            if (!defaultValue) {
              defaultValue = tmpObj
            }
          }
        })
      this.fetching = false

      if (!value && !this.defaultSelectArray) {
        this.defaultSelectArray = this.selectArray
      }

      if (this.selected && !this.modelValue && defaultValue) {
        this.defaultValue = this.radio ? defaultValue : [defaultValue]
        this.handleChange(this.defaultValue)
        return
      }
    },
    handleChange(value) {
      let tmpVal = undefined,
        tmpObj = undefined
      if (this.radio) {
        if (value) {
          tmpVal = value.key
          tmpObj = this.haveSearchObj[tmpVal]["data"]
        }
      } else {
        if (this.$func.isArray(value)) {
          tmpVal = []
          tmpObj = []
          for (let ii in value) {
            tmpVal.push(value[ii].key)
            tmpObj.push(this.haveSearchObj[value[ii].key]["data"])
          }
        }
      }

      this.emitChange = true

      this.$emit("change-model", tmpVal)
      this.$emit("change", tmpObj, this.extData)
    },
  },
}
</script>

<style lang="less" type="text/less" scoped></style>
